//
// Created by Amon on 2021/11/13.
//

#include "IOCanary.h"
#include "CrashAnalyser.h"

iocanary::_iocanary_java iocanary_java;

void iocanary::init(JNIEnv *env) {
    iocanary_java.jniEnv = env;
    jclass _io_canary_java_clazz =
            iocanary_java.jniEnv->FindClass("com/amon/canary/IOCanary");
    iocanary_java.file_io_canary_java_clazz = static_cast<jclass>(env->NewGlobalRef(
            _io_canary_java_clazz));
    iocanary_java.get_java_stack_mid =
            iocanary_java.jniEnv->GetStaticMethodID(iocanary_java.file_io_canary_java_clazz,
                                                    "getJavaStack",
                                                    "()Ljava/lang/String;");
}

void iocanary::IoCanary::OnRead(int fd, ssize_t size, int64_t cost_time) {
    if (info_map.find(fd) == info_map.end()) {
        return;
    }
    FileInfo *fileInfo = info_map.at(fd);
    fileInfo->buffer_size = size;
    fileInfo->total_cost_time += cost_time;
}

void iocanary::IoCanary::OnWrite(int fd, ssize_t size, int64_t cost_time) {
    if (info_map.find(fd) == info_map.end()) {
        return;
    }
    FileInfo *fileInfo = info_map.at(fd);
    fileInfo->buffer_size = size;
    fileInfo->total_cost_time += cost_time;
}

void iocanary::IoCanary::OnClose(int fd) {
    if (info_map.find(fd) == info_map.end()) {
        return;
    }
    FileInfo *fileInfo = info_map.at(fd);
    if (fileInfo->buffer_size < PAGE_SIZE) {
        LOGE("缓冲区域太小:%ld", fileInfo->buffer_size);
    }
    if (fileInfo->total_cost_time > 100) {
        LOGE("主线程操作文件太耗时:%ld", fileInfo->total_cost_time / 1000);
    }
    info_map.erase(fd);
    delete fileInfo;
}

void iocanary::IoCanary::OnOpen(int fd, const std::string &file_path) {
    auto _javaStack = (jstring) iocanary_java.jniEnv->CallStaticObjectMethod(
            iocanary_java.file_io_canary_java_clazz,
            iocanary_java.get_java_stack_mid);
    const char *javaStack = iocanary_java.jniEnv->GetStringUTFChars(_javaStack, JNI_FALSE);
    char *cpJavaStack = strdup(javaStack);
    iocanary_java.jniEnv->ReleaseStringUTFChars(_javaStack, javaStack);
    LOGE("stack:%s", cpJavaStack);
    auto *fileInfo = new FileInfo(file_path, cpJavaStack);
    info_map.insert(std::make_pair(fd, fileInfo));
}
